package view;


// Class by Robin Abraham
// for finding roots.

import java.math.*;
import java.util.*;

public class Roots{
    
    private final BigInteger one	= BigInteger.valueOf(1);
    private final BigInteger four	= BigInteger.valueOf(4);
    private BigInteger p;
    private BigInteger q;
    private BigInteger n;
    private BigInteger cipher;
	private BigInteger roots[] = new BigInteger[4];
	//roots = new BigInteger[4];    
   
	public Roots(BigInteger a, BigInteger b, BigInteger c){
		p = a;
		q = b;
		n = p.multiply(q);	
		cipher = c;
		//System.out.println("Roots created with " + p.toString() + " "+ q.toString() + " "+c.toString());
		
		}


    public BigInteger[] computeRoots(){   
	    BigInteger r, s, m1, m2,  r1, r2, exp;
		BigInteger a,b,x,y;
		EEC eec;
		exp = p.add(one).divide(four);
		r = cipher.modPow(exp, p);
		exp = q.add(one).divide(four);
		s = cipher.modPow(exp, q);
		
		
		if (p.compareTo(q) > 0){
			eec = new EEC(p,q);
		} else {
			eec = new EEC(q,p);
		}
		
		eec.compute();
		a = eec.getA();
		b = eec.getB();
		
		x = a.multiply(p).multiply(s).add(b.multiply(q).multiply(r)).mod(n);
		y = a.multiply(p).multiply(s).add(b.multiply(q).multiply(r).negate()).mod(n);
		roots[0] = x;
		roots[1] = y;
		roots[2] = x.negate().mod(n);
		roots[3] = y.negate().mod(n);		
		//System.out.println("\n\n Roots are: ");
		//System.out.println("x :" + x.toString());
		//System.out.println("y :" + y.toString());
		//System.out.println("root1 :" + roots[0].toString());
		//System.out.println("root2 :" + roots[1].toString());
		//System.out.println("root3 :" + roots[2].toString());
		//System.out.println("root4 :" + roots[3].toString());		
//		return roots;
		


/*		
		r1 = r.negate().mod(p);
		r2 = s.negate().mod(q);
		m1 = q.modInverse(p);
		m2 = p.modInverse(q);

		roots[0] = ((r.multiply(m1).multiply(q)).add(r1.multiply(m2).multiply(p))).mod(n);
		roots[1] = ((r.multiply(m1).multiply(q)).add(r2.multiply(m2).multiply(p))).mod(n);
		roots[2] = ((s.multiply(m1).multiply(q)).add(r1.multiply(m2).multiply(p))).mod(n);
		roots[3] = ((s.multiply(m1).multiply(q)).add(r2.multiply(m2).multiply(p))).mod(n);
		
	
		System.out.println("\n\n Roots are: ");
		System.out.println("root1 :" + roots[0].toString());
		System.out.println("root2 :" + roots[1].toString());
		System.out.println("root3 :" + roots[2].toString());
		System.out.println("root4 :" + roots[3].toString());		
*/
		if(cipher.compareTo(roots[0].modPow(BigInteger.valueOf(2),n)) != 0)System.out.println("****INCORRECT***");
		if(cipher.compareTo(roots[1].modPow(BigInteger.valueOf(2),n)) != 0)System.out.println("****INCORRECT***");
		if(cipher.compareTo(roots[2].modPow(BigInteger.valueOf(2),n)) != 0)System.out.println("****INCORRECT***");
		if(cipher.compareTo(roots[3].modPow(BigInteger.valueOf(2),n)) != 0)System.out.println("****INCORRECT***");

		return roots;


    }
 

  
}

